iOS/Swift: Custom UIProgressView

by DaoNM2
1.4K views

Lời mở đầu

Có thể các bạn đã biết progress view của Apple nó khá là đơn giản và ýt thuộc tính để chúng ta có thể sử dụng cũng như thay đổi để phù hợp với thiết kế. Trong dự án gần đây mình đã có cơ hội để động vào nó. Trong thời gian đầu mình tự mày mò thì progress bar không hỗ trợ việc như vậy. Vì vậy mình viết bài này để chia sẻ về cách mình đã custom lại progress này. Hi vọng nó giúp các bạn gặp khó khăn với việc custom lại progress bar.

Vấn đề cần giải quyết: Làm thế nào để bo tròn góc của progress bar

Đây là progress view mình cần đạt được:

Đây là progress bar mặc đinh của apple:

Phân tích

Khi thử đọc tài liệu về UIProgressView. Không có thuộc tính nào giúp mình có thể đạt được điều mình muốn.

Để bo tròn cả progressview thì ta có thể dùng layer.cornerRadius, nhưng để bo tròn thằng progress chạy bên trong thì sao? Chúng ta cần tìm được cái view đó và bo nó lại.

Giải quyết bài toán

Bước 1: Chúng ta cần tạo constraint height cho progressView

Chúng ta có 2 cách để tăng height cho ProgressView:
1. Sử dụng Transform Scale: Nó sẽ làm cornerRadius chạy không đúng
2. Sử dụng constraint height: Nên chúng ta chon cách này

Tuy rằng chúng ta đã constraint height của nó bằng 16 nhưng thực tế height của progressView vẫn = 2. Vì vậy khi set cornerRadius chúng ta không thể sử dụng frame.height/2 được mặc dù đó là cách tốt nhất đối với các view khác.

Bước 2: Bo tròn góc cho trackView

progressBar.layer.cornerRadius = 8.0
progressBar.clipsToBounds = true

Bước 3: Bo tròn progressView

        if let sublayers = progressBar.layer.sublayers, sublayers.count > 1 {
            sublayers[1].cornerRadius = 8.0
        }
        progressBar.subviews[1].clipsToBounds = true

Nếu để ý kĩ các bạn sẽ thấy progress bar này gồm 2 view chồng lên nhau đó là Progress View và track view. Và theo thứ tự trong lập trình thì thằng đầu tiên là thằng nằm dưới có index = 0. Chúng ta nhìn thấy progress view vì nó nằm trên Track View -> nó có index = 1

Lưu ý: Nó chỉ đúng khi chúng ta không thêm subview, sublayer cho ProgressView. Vậy nên trong trường hợp này chúng ta sẽ ổn.

If let giúp chúng ta handle trường hợp crash app, khi các layer của progress bị remove. (nó thường k xảy ra, nhưng vì an toàn chúng ta nên thêm dòng này)

sublayers[1]: là layer của track view
subviews[1]: là trackView

Kết quả thu được thật mỹ mãn 😀

Ngoài ra các bạn có thể sử dụng image cho progress view cũng như trackView để có 1 progress đẹp hơn.

progressBar.progressImage = UIImage(named: "2697")

Các bạn có thể tải về file assets ở dưới:

Tổng kêt

Mình hi vọng bài viết dưới đây giúp các bạn hiểu rõ hơn về UIProgressView và dễ dàng hơn khi làm việc với nó.

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.