- vừa được xem lúc

Tạo Semi Circular Progress cho iOS

0 0 24

Người đăng: Trần Đạt

Theo Viblo Asia

Mở đầu

Khi làm dự án cho công ty hoặc khách hàng, đôi lúc bạn sẽ nhận được yêu cầu tạo những giao diện liên quan tới hình vẽ, khối mà dùng hình ảnh thì khó mà dùng thư viện thì chẳng bõ, khi ấy chúng ta sẽ cần sử dụng tới những tính năng cho phép vẽ custom lên UIView.

Trong bài lần này mình sẽ chia sẻ cách tạo 1 Progress theo dạng đường tròn khuyết (Semi Circular Progress) bằng CAShapeLayer.

Demo

Demo trên iOS

Thực hiện

Tạo Custom View

Tạo 1 project mới để demo, từ file dự án tạo 1 file kế thừa UIView ở đây mình đặt là SemiCircleView. Ta sẽ tiến hành dùng CAShapeLayer vẽ progress ở trên CustomView này

Ta sẽ cần 2 layer, 1 cho background màu xám ở dưới và 1 cho phần màu xanh thay đổi được nên ta sẽ tạo ra 2 ShapeLayer lần lượt là backgroundLayermainLayer

class SemiCircleView: UIView { private var backgroundLayer: CAShapeLayer? private var mainLayer: CAShapeLayer?
}

Hàm cài đặt cho CustomView

Ta tạo hàm setup với tham số truyền vào là UIColor tương ứng với màu progress bạn muốn vẽ, lần lượt viết các lệnh vẽ path cho ShapeLayer

func setupUI(color: UIColor) { // Remove layer trước khi thêm để tránh view chèn vào nhiều layer, // Phần này sẽ giúp bạn tránh vẽ đè khi gọi là hàm setup mainLayer?.removeFromSuperlayer() backgroundLayer?.removeFromSuperlayer() // Khởi tạo lại layer mainLayer = CAShapeLayer() backgroundLayer = CAShapeLayer() let center = CGPoint(x: frame.width/2, y: frame.height/2) // center nằm ở giữa view cha let circularPath = UIBezierPath(arcCenter: center, // tâm đường tròn radius: frame.height/2, // bán kính đường tròn startAngle: CGFloat.pi * 3/4, // điểm vẽ đầu endAngle: CGFloat.pi * 13/6, // điểm vẽ cuối clockwise: true) // Vẽ theo chiều kim đồng hồ mainLayer?.path = circularPath.cgPath backgroundLayer?.path = circularPath.cgPath setupSubLayer(backgroundLayer, color: UIColor.separator, progress: 1) setupSubLayer(mainLayer, color: color, progress: 0) }

Tiếp theo là hàm setup của ShapeLayer, sau setup ta sẽ add vào thành subLayer của SemiCircleView

private func setupSubLayer(_ shapeLayer: CAShapeLayer?, color: UIColor, progress: CGFloat) { shapeLayer?.fillColor = UIColor.clear.cgColor // Màu của layer shapeLayer?.strokeEnd = progress // Độ phủ của stroke, tính theo %, max là 1 shapeLayer?.strokeColor = color.cgColor // Màu của stroke shapeLayer?.lineWidth = 12 // Độ rộng stroke shapeLayer?.lineCap = .round // Hình dạng 2 đầu stroke (round là bo tròn) if let sub = shapeLayer { layer.addSublayer(sub) } }

Cuối cùng ta sẽ viết hàm để thay đổi giá trị progress

func setProgress(_ progress: Float) { UIView.animate(withDuration: 0.3) { // Đặt hiệu ứng cho chuyển động bắt mắt hơn self.mainLayer?.strokeEnd = CGFloat(progress) } }

Demo

Ở Story board Main ta thêm View có kích thước 200 x 200 căn giữa view cha và cho kế thừa SemiCircleView ta vừa tạo.

Tiếp theo ta kéo thêm 1 label hiển thị giá trị progress và 1 button thay đổi giá trị progress.

Ở class ViewController ta chỉ cần gọi setup cho SemiCircleViewviewDidLoad và gọi hàm setProgress mỗi khi click button thay đổi progress là sẽ có được phần giao diện thay đổi progress bar tròn như hình phía đầu bài viết.

class ViewController: UIViewController { @IBOutlet weak var semiCircleView: SemiCircleView! @IBOutlet weak var progressLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() semiCircleView.setupUI(color: .systemBlue) semiCircleView.setProgress(0) } @IBAction func recTap(_ sender: UIButton) { let progress = Int.random(in: 0...100) progressLabel.text = "\(progress) %" semiCircleView.setProgress(Float(progress)/100) } }

Kết thúc

Bài viết này mình đã chia sẻ về cách đơn giản để tạo 1 Progress Bar tròn khuyết dùng CAShapeLayer, mong rằng chia sẻ này sẽ giúp ích cho các bạn.

Xin cảm ơn các bạn đã dành thời gian đọc bài viết và nếu thấy bổ ích hãy cho mình +1 đánh giá động viên nhé!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 281

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 214

- vừa được xem lúc

Swift: Tạo custom phép toán tử (Operator) của riêng bạn!

Swift cho phép bạn tạo các toán tử có thể tùy chỉnh của riêng bạn. Điều này đặc biệt hữu ích khi bạn xử lý các loại dữ liệu của riêng mình. Operator Types in Swift. Có năm loại toán tử chính trong Swift.

0 0 56

- vừa được xem lúc

Chương 6 Protocol oriented programming.

Cuốn sách này là về lập trình hướng protocol. Khi Apple thông báo swift 2 ở WWDC 2015.

0 0 48

- vừa được xem lúc

Ví dụ về UIActivityViewController

Trên iOS, UIActivityViewController cung cấp giao diện thống nhất để người dùng chia sẻ và thực hiện các hành động trên văn bản, hình ảnh, URL và các mục khác trong ứng dụng. let string = "Hello, world!". let url = URL(string: "https://nshipster.com").

0 0 58

- vừa được xem lúc

Quản lý self và cancellable trong Combine.

. . Công việc quản lý bộ nhớ memory management thường trở nên phức tạp khi chúng ta thực hiện các tác vụ bất đồng bộ asynchronous vì chúng ta thường phải lưu giữ một số object nằm ngoài scope mà object được define trong khi vẫn phải đảm bảo được việc giải phóng object đó được thực hiện đúng quy trìn

0 0 41