Chào các bạn, chúng ta đều biết rằng, công cụ Xcode có thể giúp chúng ta có thể thiết kế giao diện trực quan và nhanh chóng, khi đó chúng ta dùng storyboard hay xib, nhưng nhiều khi bạn cần viết giao diện bằng code. Nếu bạn nắm được cách viết giao diện bằng code bạn có thể hiểu sâu hơn những vấn đề khi làm giao diện.
Hôm nay mình sẽ hướng dẫn làm giao diện bằng code nhé, để hiểu được phải code như thế nào thì chúng ta sẽ đi từ việc kéo thả giao diện:
Đã xong, không cần viết một dòng code, chúng ta vẫn hoàn thành được giao diện login, vậy khi code thì chúng ta sẽ code cái gì.
Trước khi sử dụng thư viện, mình hướng dẫn các bạn code chay nhé:
Đầu tiên chúng ta muốn cái gì xuất hiện trên giao diện thì chúng ta phải khởi tạo cái đó, ở đây mình khởi tạo đối tượng username và usernameTextField:
let userName: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "User Name:"
label.textAlignment = .left
label.font = UIFont.systemFont(ofSize: 16)
label.textColor = .black
return label
}()
let userNameTextFiled: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Click here"
textField.font = UIFont.systemFont(ofSize: 18)
textField.borderStyle = UITextField.BorderStyle.roundedRect
return textField
}()
Một thuộc tính rất quan trọng khi bạn khởi tạo đối tượng là bạn phải thiết lập translatesAutoresizingMaskIntoConstraints bằng false, mặc định là true theo tọa độ thông thường là frame và dùng AutoresizingMask.
Tiếp theo, chúng ta layout cho đối tượng:
//username
view.addSubview(userName)
userName.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
userName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
userName.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
userName.heightAnchor.constraint(equalToConstant: 24).isActive = true
//username textfield
view.addSubview(userNameTextFiled)
userNameTextFiled.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 8).isActive = true
userNameTextFiled.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
userNameTextFiled.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
userNameTextFiled.heightAnchor.constraint(equalToConstant: 44).isActive = true
Ở đây khi layout cho đối tượng, mình đã sử dụng NSLayoutAnchor thay vì NSLayoutConstraint, vì khi sử dụng NSLayoutAnchor, bạn sẽ thấy ngắn gọn và dễ hiểu hơn, và nó cũng khá dễ để hình dung (gần giống với việc AutoLayout trên Storyboard)
Để thấy nó ngắn hơn như thế nào bạn có thể xem đoạn code sau đây:
// C1: Sử dụng NSLayoutConstraint
let constaint = NSLayoutConstraint(item: userName,
attribute: .height,
relatedBy: .equal,
multiplier: 1.0,
constant: 0)
// C2: Sử dụng NSLayoutAnchor
userName.heightAnchor.constraint(equalToConstant: 24).isActive = true
Qua ví dụ trên có thể thấy rõ các ưu điểm đã nêu của NSLayoutAnchor. Cách dùng cũng rất đơn giản, ở đây heightAnchor là: NSLayoutDimension chính là các thuộc tính sẽ được sử dụng để layout, ngoài heightAnchor ra có rất nhiều các thuộc tính khác như widthAnchor, topAnchor, leftAnchor, rightAnchor, bottomAnchor, ... (Chỉ cần gõ ten_doi_tuong.anchor XCode sẽ suggest ra các thuộc tính).
Quay lại với bài của chúng ta, khi mỗi đối tượng chúng ta đều phải layout lặp đi lặp lại và mã code sẽ trở nên rất cồng kềnh, dưới đây là toàn bộ đoạn code để ra giao diện như chúng ta đã thấy ban đầu
import UIKit
class ViewController: UIViewController {
let userName: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "User Name:"
label.textAlignment = .left
label.font = UIFont.systemFont(ofSize: 16)
label.textColor = .black
return label
}()
let userNameTextFiled: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Click here"
textField.font = UIFont.systemFont(ofSize: 18)
textField.borderStyle = UITextField.BorderStyle.roundedRect
return textField
}()
let password: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Password:"
label.textAlignment = .left
label.font = UIFont.systemFont(ofSize: 16)
label.textColor = .black
return label
}()
let passwordTextFiled: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = " Click here"
textField.font = UIFont.systemFont(ofSize: 18)
textField.borderStyle = UITextField.BorderStyle.roundedRect
return textField
}()
let login: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .gray
button.setTitle("Login", for: .normal)
button.contentHorizontalAlignment = .center
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
button.setTitleColor(UIColor.white, for: .normal)
button.layer.cornerRadius = 5.0
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
setupLayout()
}
func setupLayout(){
//username
view.addSubview(userName)
userName.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
userName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
userName.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
userName.heightAnchor.constraint(equalToConstant: 24).isActive = true
//username textfield
view.addSubview(userNameTextFiled)
userNameTextFiled.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 8).isActive = true
userNameTextFiled.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
userNameTextFiled.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
userNameTextFiled.heightAnchor.constraint(equalToConstant: 44).isActive = true
//password
view.addSubview(password)
password.topAnchor.constraint(equalTo: userNameTextFiled.bottomAnchor, constant: 16).isActive = true
password.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
password.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
password.heightAnchor.constraint(equalToConstant: 24).isActive = true
//password textfield
view.addSubview(passwordTextFiled)
passwordTextFiled.topAnchor.constraint(equalTo: password.bottomAnchor, constant: 8).isActive = true
passwordTextFiled.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
passwordTextFiled.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
passwordTextFiled.heightAnchor.constraint(equalToConstant: 44).isActive = true
//login
view.addSubview(login)
login.topAnchor.constraint(equalTo: passwordTextFiled.bottomAnchor, constant: 32).isActive = true
login.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
login.widthAnchor.constraint(equalToConstant: 100).isActive = true
login.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
Giao diện sẽ được như sau:
Woa, để hiển thị được một chút giao diện mà phải code rất chi là dài dòng, thế nên mình sẽ giới thiệu với các bạn cách khác ngắn hơn nhé.
Chúng ta sẽ sử dụng thư viện Stevia - một thư viện Layout dành cho iOS:
Để sử dụng các thư viện ngoài thì máy tính của bạn cần phải cài đặt Cocoa Pod:
Stevia là thư viện ngoài thế nên chúng ta cần thực hiện một vài bước trước khi bắt tay vào code.
B1: Cài đặt Cocoa Pod (bước này chỉ cài lần đầu, máy đã cài Cocoa Pod thì bỏ qua bước này nhé):
$ sudo gem install cocoapods
B2: Tạo project (cái này easy phải không)
B3: Bật Terminal cd đến thư mục project vừa tạo và enter
$ cd /Users/Desktop/DemoSteviaLayout
B4: Gõ lệnh pod init
$ pod init
B5: Mở Pod file trong project
B6: Thêm lệnh sau vào Podfile :
pod 'SteviaLayout'
sau đó lưu file: cmd + S hoặc File -> Save
B7: Trong terminal, gõ lệnh
$ pod install
B8: Sau khi Install xong, bạn tắt cửa sổ project vừa tạo, vào project mở file có đuôi .xcworkspace
B9: Đã xong, giờ thì chúng ta code thôi
Chúng ta mở file DemoSteviaLayout.xcworkspace, vào ViewController.swift thêm thư viện Stevia
Chúng ta vẫn cần khai báo các đối tượng nhé:
let username = UILabel()
let usernameTextField = UITextField()
let password = UILabel()
let passwordTextField = UITextField()
let login = UIButton()
Trong viewDidLoad(), chúng ta sẽ thêm các đối tượng trên vào view:
view.sv(
username,
usernameTextField,
password,
passwordTextField,
login
)
sv([]) và sv() là cách gọi khác của addSubview() và translateAutoresizingMaskIntoConstraints = false
Layout các đối tượng:
username.top(50).left(30).right(30).height(40)
==
view.layout(
50,
|-30-username-30-| ~ 40,
)
Các bạn layout tương tự với các đối tượng còn lại, chúng ta sẽ được:
//layout
view.layout(
50,
|-30-username-30-| ~ 40,
8,
|-30-usernameTextField-30-| ~ 40,
16,
|-30-password-30-| ~ 40,
8,
|-30-passwordTextField-30-| ~ 40,
32,
|-100-login-100-|
)
Sau khi layout xong, chúng ta sẽ set đến font, color, text, ...
//style
usernameTextField.style(textFieldStyle)
passwordTextField.style(textFieldStyle)
login.style(buttonStyle)
//content
username.text = "User Name:"
usernameTextField.placeholder = "Text here"
password.text = "Password:"
passwordTextField.placeholder = "Text here"
login.setTitle("Login", for: .normal)
textFieldStyle và buttonStyle mình viết thành hàm riêng để có thể sử dụng lại nhiều lần:
func textFieldStyle(_ f: UITextField){
f.borderStyle = .roundedRect
f.font = UIFont.systemFont(ofSize: 18)
}
func buttonStyle(_ b: UIButton){
b.backgroundColor = .gray
b.setTitleColor(.white, for: .normal)
b.layer.cornerRadius = 10
}
Sau đó, bạn hãy Run project và giao diện sẽ được như sau:
Như vậy là chúng ta đã layout xong giao diện Login dưới sự hỗ trợ của thư viện, nếu bạn là developer iOS, bạn sẽ thích cách nào 😀
Dưới đây là toàn bộ mã code của mình khi sử dụng thư viện Stevia
//
// ViewController.swift
// DemoSteviaLayout
//
import UIKit
import Stevia
class ViewController: UIViewController {
let username = UILabel()
let usernameTextField = UITextField()
let password = UILabel()
let passwordTextField = UITextField()
let login = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
//addSubview
view.sv(
username,
usernameTextField,
password,
passwordTextField,
login
)
//layout
view.layout(
50,
|-30-username-30-| ~ 40,
8,
|-30-usernameTextField-30-| ~ 40,
16,
|-30-password-30-| ~ 40,
8,
|-30-passwordTextField-30-| ~ 40,
32,
|-100-login-100-|
)
//style
usernameTextField.style(textFieldStyle)
passwordTextField.style(textFieldStyle)
login.style(buttonStyle)
//content
username.text = "User Name:"
usernameTextField.placeholder = "Text here"
password.text = "Password:"
passwordTextField.placeholder = "Text here"
login.setTitle("Login", for: .normal)
}
func textFieldStyle(_ f: UITextField){
f.borderStyle = .roundedRect
f.font = UIFont.systemFont(ofSize: 18)
}
func buttonStyle(_ b: UIButton){
b.backgroundColor = .gray
b.setTitleColor(.white, for: .normal)
b.layer.cornerRadius = 10
}
}
Các bài viết tiếp theo mình sẽ layout một số giao diện phức tạp hơn, các bạn chờ đón đọc nhé 😊
Bình luận