Tìm hiểu về stack view trên iOS 9
Khi iOS 9 được Apple ra mắt, Apple đã mang đến rất nhiều tính năng mới để các lập trình viên có thể sử dụng trong quá trình viết app của mình. Trong số đó, stack view là một tính năng mới rất tuyệt vời được Apple cung cấp. Với việc sử dụng stack view, lập trình viên có thể làm giảm độ phức tạp ...
Khi iOS 9 được Apple ra mắt, Apple đã mang đến rất nhiều tính năng mới để các lập trình viên có thể sử dụng trong quá trình viết app của mình. Trong số đó, stack view là một tính năng mới rất tuyệt vời được Apple cung cấp.
Với việc sử dụng stack view, lập trình viên có thể làm giảm độ phức tạp trong việc sắp xếp và tính toán hệ thống các views khi thiết kế views của view controller trong storyboard, giảm việc sử dụng nhiều constraints, giúp cho việc quản lý các UIViewControllers, UIViews đơn giản và dễ ràng hơn rất nhiều
Khi các UIViews được sắp xếp trong stack view, lập trình viên không phải thực hiện việc thêm các constraint cho các UIViews nữa, việc điều chỉnh kích thước của các UIView sẽ do stack view tự động thực hiện. Như vậy, khi việc quản lý các UIViews khi làm việc với nhiều khích thước màn hình khác nhau(iphone 4, iphone 5, iphone 6, iphone 6+, ipad,...) sẽ đơn giản và dễ dàng hơn rất nhiều
Ngoài ra, trong quá trình runtime, việc sử dụng Stack view sẽ hỗ trợ chúng ta rất nhiều trong một vài trường hợp. Ví dụ, giả sử chúng ta có 1 UIViewController với 3 UIButton được sắp xếp từ trên xuống dưới, và chúng ta muốn khi click vào 1 UIButton bất kỳ, thì UIButton ở giữa sẽ biến mất hoặc xuất hiện lại và UIButton bên dưới sẽ được đẩy lên/ đẩy xuống để lấp khoảng trống của UIButton ở giữa. Nếu sử dụng constraint, chúng ta sẽ phải thêm constraint cho 3 button, và thêm Outlet cho UIButton bên dưới để tính toán khi muốn đẩy button đó lên/ xuống. Khi sử dụng stack view, chúng ta không phải làm gì cả, stack view của chúng ta sẽ tự động làm giúp chúng ta những việc trên.
Người viết xin gửi đến các bạn app demo dưới đây về việc sử dụng stack view để các bạn có thể nắm rõ hơn về việc sử dụng stack view và những ích lợi mà stack view mang lại. Sau khi hoàn thành project demo này, chúng ta sẽ tạo được một app với màn hình như sau:
1. Tạo project
Đầu tiên, chúng ta tạo project mới. Mở Xcode, tạo new -> project -> Single View Application, đặt tên "StackViewsTutorial", chọn ngôn ngữ Swift và tạo project. Lưu ý, stack view chỉ sử dụng được từ iOS 9, vì vậy chúng ta cần sử dụng xcode 7 và để Deployment target là 9.0
Chúng ta cần 1 ít ảnh để sử dụng trong app demo này, các bạn có thể download một vài ảnh ví dụ sau: image01.jpg , image02.jpg , image03.jpg
Chúng ta download ảnh về và kéo vào image assets của project.
2. Implement stack view
Bây giờ, chúng ta bắt đầu code cho app của chúng ta. Trong file Main.storyboard, từ Object library, chúng ta kéo và thả để thêm Vertical Stack view vào view controller, chỉnh kích thước của Vertical Stack View là (0, 0, 600, 600), và thêm các constraints để các cạnh của stack view trùng với các cạnh của Super View như trong hình sau:
Tiếp theo, chúng ta kéo 3 UIImage vào trong stack view vừa tạo, chỉnh thuộc tính mode của các UIImage lần lượt về "Aspect fill", chọn thuộc tính "clip subviews" và điền lần lượt tên các ảnh chúng ta vừa download cho các UIImage.
Oops, Sau khi thêm các ảnh vào stack view, các ảnh sắp sếp không được hợp lý, 1 ảnh bị che khuất và xcode báo lỗi đỏ do lỗi conflict giao diện
Mở Attributes inspector của stack view, để ý các thuộc tính của Stack view, chúng ta thấy:
- Axis: Chiều sắp xếp của stack view, chúng ta có thể chọn Vertical hoặc Horizontal để chọn stack theo chiều dọc hay chiều ngang
- Alignment: vị trí sắp xếp của mỗi view con trong stack view. Đối với Vertical stack, chúng ta có các thuộc tính fill, leading, center, trailing; và đối với Horizontal stack là fill, top, center và bottom
- Distribution: sự phân bổ, sắp xếp của các view con trong stack. với mỗi thuộc tính distribution khác nhau, các view con sẽ được sắp xếp khác nhau. Ở đây chúng ta có các lựa chọn: fill, fill equally, fill proportionally, equal spacing, equal centering
- Spacing: khoảng cách giữa các view con trong stack view.
Trong app demo này, chúng ta chọn lần lượt Axis là vertical, alignment là fill, distribution là fill equally và để spacing là 10.
Bây giờ chạy thử project, các bạn sẽ thấy app của chúng ta đã có 1 màn hình với 3 UIImageView được sắp xếp dọc màn hình, chia đều màn hình thành 3 phần bằng nhau. Dù chúng ta chạy trên kích thước màn hình nào, portrait hay landscape kết quả cũng tương tự nhau.
Lưu ý: sau khi chọn các thuộc tính cho stack view, nếu xcode báo lỗi warning trong document outline, các bạn có thể chỉnh qua lại thuộc tính "mode" của stack view từ "scale to fill" sang "aspect fill" để loại bỏ warning này. Đây có lẽ là 1 lỗi của xcode mỗi khi chúng ta điều chỉnh các thuộc tính của stack view và xcode không xác định được kích thước của các view sau khi chúng ta điều chỉnh.
3. phức tạp hơn: tạo các stack view lồng nhau
Ở trên, chúng ta đã tạo được 1 stack view với 3 UIImage. Bây giờ, chúng ta sẽ thêm 3 UIButton vào trong stack view.
Vì 3 button được sắp sếp theo chiều ngang, chúng ta sẽ sắp xếp 3 button vào 1 horizontal stack view, rồi cả horizontal stack view của các button và vertical stack view của 3 ảnh chúng ta tạo bên trên sẽ được sắp xếp trong 1 vertical stack view lớn bên ngoài.
Để thực hiện việc này, chúng ta lần lượt làm theo các bước sau:
- Bước 1: trong document outlet, chọn vertical stack view chứa các UIImage ở trên, bấm vào nút stack để tạo stack như hình sau:
chúng ta chỉnh lần lượt các thuộc tính của stack này là Axis vertical, Alignment fill, distribution fill, space 20.
Sau khi stack view, các view của chúng ta có vẻ bị lệch rất nhiều so với chúng ta mong muốn. Đừng lo lắng, sau khi thực hiện bước 2, các views của chúng ta sẽ không còn bị lệch nữa
- Bước 2: chúng ta thêm các constraints cho stack view mới thêm với 4 cạnh của super view, lần lượt để các constraints bằng 0 với top và bottom và -20 với trailing và leading để các cạnh của stack view trùng với các cạnh của super view. Nếu các view không tự điều chỉnh, các bạn update frame để frame của các view tự động update theo constraints vừa tạo
- Bước 3: Kéo thêm 1 horizonal stack view từ object library vào trong stack vừa tạo, để các thuộc tính là axis horizonal, alignment center, distribution equal spacing.
- Bước 4: thêm 3 UIButton vào horizonal stack vừa tạo. đặt title cho 3 button lần lượt là Hide image 1, hide image 2, hide image 3.
Sau khi hoàn thành việc kéo và điều chỉnh thuộc tính cho các views, controller của chúng ta sẽ có hệ thống các view con như sau:
Đến thời điểm này, chúng ta đã tạo đủ các views cho controller. Tiếp theo, chúng ta sẽ bắt đầu viết code để thực hiện việc show/hide các ảnh
4. Coding: show/hide ảnh
Đầu tiên, chúng ta mở assitant editor, kéo và tạo lần lượt các outlet cho các UIImage và UIbutton:
@IBOutlet weak var image1: UIImageView! @IBOutlet weak var image2: UIImageView! @IBOutlet weak var image3: UIImageView! @IBOutlet weak var button1: UIButton! @IBOutlet weak var button2: UIButton! @IBOutlet weak var button3: UIButton!
Tiếp theo, kéo và tạo các action cho các button:
@IBAction func onButton1Clicked(sender: AnyObject) { } @IBAction func onButton2Clicked(sender: AnyObject) { } @IBAction func onButton3Clicked(sender: AnyObject) { }
Bây giờ, chúng ta sẽ viết code lần lượt cho các button, nếu image ứng với button đó đang được hiển thị, thì chúng ta ẩn image đó đi, đổi title cho button và ngược lại.
@IBAction func onButton1Clicked(sender: AnyObject) { if image1.hidden == false { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image1.hidden = true self.button1.setTitle("Show image 1", forState: UIControlState.Normal) }) } else { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image1.hidden = false self.button1.setTitle("Hide image 1", forState: UIControlState.Normal) }) } } @IBAction func onButton2Clicked(sender: AnyObject) { if image2.hidden == false { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image2.hidden = true self.button2.setTitle("Show image 2", forState: UIControlState.Normal) }) } else { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image2.hidden = false self.button2.setTitle("Hide image 2", forState: UIControlState.Normal) }) } } @IBAction func onButton3Clicked(sender: AnyObject) { if image3.hidden == false { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image3.hidden = true self.button3.setTitle("Show image 3", forState: UIControlState.Normal) }) } else { UIView.animateWithDuration(0.3, animations: { () -> Void in self.image3.hidden = false self.button3.setTitle("Hide image 3", forState: UIControlState.Normal) }) } }
Vậy là app demo của chúng ta đã hoàn thành. Chạy thử project và bấm lần lượt các button để xem kết quả. Như các bạn thấy, các image của chúng ta đã có thể được ẩn và hiện cực kỳ mượt mà, khi một image bị ẩn hoặc hiện ra, các view phía bên dưới sẽ được dồn lên/xuống một cách tự động và rất mượt mà. Điều này là rất tuyệt vời, bởi vì trước khi stack view xuất hiện, chúng ta sẽ phải tốn rất nhiều công sức để tạo các constraints cho các view của chúng ta để căn cho các kích thước màn hình, và khi chạy app, chúng ta phải tính toán lại các constraints để xếp lại các view khi ẩn/hiện một view
Trên đây, tôi đã giới thiệu đến các bạn stack view: một công cụ mới hết sức tuyệt vời để sử dụng trong lập trình iOS. Với việc sử dụng stack view, chúng ta có thể giảm thiểu công sức rất nhiều trong việc sử dụng auto layout, tính toán constraints cho nhiều kích thước màn hình và loại bỏ việc phải tính lại constraints trong code. Ngoài ra, việc sử dụng stack view cũng giúp chúng ta rất nhiều trong việc maintain code sau này do tính đơn giản, dễ quản lý của nó. Hi vọng bài viết này sẽ giúp ích cho các bạn trong việc tìm hiểu về stack view.
Trong bài viết, tôi chỉ tạo app demo với mục đích hướng dẫn áp dụng stack view vào trong code, nên app demo này không được đẹp cho lắm, mong các bạn thông cảm. Các bạn có thể download project này tại đây
Cuối cùng, người viết xin cảm ơn các bạn đã theo dõi bài viết này!