Dùng UIScrollView để zoom ảnh
I. Giới thiệu Bạn muốn tạo một playlist các ảnh có size khác nhau và zoom in zoom out chúng, có 2 cách để làm được như vậy: Cách thứ nhất là dùng pinch gesture Cách thứ hai dùng UIScrollView Trong bài viết này, mình sẽ dùng UIScrollView để thực hiện Bắt đầu nhé! II. Nội dung Việc thực hiện ...
I. Giới thiệu
Bạn muốn tạo một playlist các ảnh có size khác nhau và zoom in zoom out chúng, có 2 cách để làm được như vậy:
Cách thứ nhất là dùng pinch gesture Cách thứ hai dùng UIScrollView Trong bài viết này, mình sẽ dùng UIScrollView để thực hiện Bắt đầu nhé!
II. Nội dung
Việc thực hiện gồm 3 bước sau:
-
Trong interface của viewcontroller, kéo 1 UIScrollView vào sau đó kéo 1 UIImageView làm subView của UIScrollView. Set delegate của scrollView là viewController.
-
Kéo outlet cho scrollView và imageView vào viewController với tên tương ứng
-
Xử lý frame cho UIScrollView và UIImageView. Đây là bước quan trọng nhất. Bản chất như sau:
a. Tạo frame cho ScrollView để nó vừa đúng bằng view của viewController bằnng cách set autoResizeMask như sau:
b. Về phía UIImageView, có nhiều việc phải làm hơn:
-
Gán size của UIImageView bằng đúng size image của nó. Thực hiện bước này sẽ khiến cho ảnh của ImageView vừa khít, ko bị thừa 2 bên lề hay bóp méo
-
Đưa imageView ở giữa màn hình bằng cách gán: imageView.center = view.center
-
private func updateSizeForImageView(size: CGSize) { imageView.center = view.center imageView.frame.size = CGSizeMake(size.awidth, size.height) }
c. Tại thời điểm này, imageView đã có size vừa đúng bằng size của image(ảnh không thừa không thiếu), và ở giữa màn hình. Tuy nhiên, chúng ta cần nhiều hơn thế. Chúng ta muốn ảnh sẽ có kích thước vừa màn hình nhất có thể(tối thiểu chiều dài hoặc chiều rộng phải bằng chiều dài và chiều rộng của màn hình) nhưng vẫn giữ nguyên tỷ lệ, vì vậy cần tính tỷ lệ zoom của scrollView như sau:
private func updateMinZoomScaleForSize(size: CGSize) { let awidthScale = size.awidth / imageView.bounds.awidth let heightScale = size.height / imageView.bounds.height let minScale = min(awidthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale }
d. Đến đây, imageView đã vừa đúng màn hình và nhìn đã rất đẹp rồi. Tuy nhiên, khi chúng ta zoom in, size của UIImageView thay đổi, nó sẽ không còn ở giữa màn hình nữa. Chúng ta cần phải đảm bảo kể cả khi zoom, ảnh vẫn luôn ở giữa màn hình bằng cách implement 2 method của UIScrollViewDelegate: - Cho scrollView biết đối tượng nó cần zoom là imageView:
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { return imageView }
- Khi zoom thực hiện tính lại origin cho imageView sao cho nó luôn ở giữa màn hình:
private func updateConstraintsForSize(size: CGSize) { let realHeight = imageView.bounds.height * scrollView.zoomScale let readWidth = imageView.bounds.awidth * scrollView.zoomScale let deltaHeight = view.bounds.height - realHeight let deltaWidth = view.bounds.awidth - readWidth let yOffset = max(0, deltaHeight/2) let xOffset = max(0, deltaWidth/2) imageView.frame.origin = CGPointMake(xOffset, yOffset) }
e. Set backgroundColor của view là blackColor(), của scrollView và imageView là clearColor để nhìn cool hơn, sau đó nhấn Build và enjoy:D
III. Tổng kết
UIScrollView ngoài việc được biết như một super class của 2 class vô cùng quen thuộc là UITableView và UICollectionView thì còn có nhiều tính năng mới rất hữu ích và việc xử lý zoom ảnh trong bài viết này chỉ là một trong số đó. Hy vọng bài viết này sẽ giúp ích được cho các bạn trong hành trình trở thành một iOS developer chuyên nghiệp:D. Happy coding!
Toàn bộ source code:
import UIKit class ViewController: UIViewController { @ IBOutlet weak var scrollView: UIScrollView! @ IBOutlet weak var imageView: UIImageView! var image = UIImage(named: "lion.jpg") override func viewDidLoad() { super.viewDidLoad() updateSizeForImageView(image!.size) updateMinZoomScaleForSize(view.bounds.size) imageView.image = image } private func updateSizeForImageView(size: CGSize) { imageView.center = view.center imageView.frame.size = CGSizeMake(size.awidth, size.height) } private func updateMinZoomScaleForSize(size: CGSize) { let awidthScale = size.awidth / imageView.bounds.awidth let heightScale = size.height / imageView.bounds.height let minScale = min(awidthScale, heightScale) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale } private func updateConstraintsForSize(size: CGSize) { let realHeight = imageView.bounds.height * scrollView.zoomScale let readWidth = imageView.bounds.awidth * scrollView.zoomScale let deltaHeight = view.bounds.height - realHeight let deltaWidth = view.bounds.awidth - readWidth let yOffset = max(0, deltaHeight/2) let xOffset = max(0, deltaWidth/2) imageView.frame.origin = CGPointMake(xOffset, yOffset) } } extension ViewController: UIScrollViewDelegate { func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { return imageView } func scrollViewDidZoom(scrollView: UIScrollView) { updateConstraintsForSize(view.bounds.size) } }