ios 自定义一个水平进度条

221 阅读1分钟

ios 自定义一个水平进度条 新的知识点 1 CADisplayLink 可以监听页面的刷新回调,理论上每一秒执行60次

todo 1 add 方法第二个参数 

2 CAShapeLayer 可以用来绘制图形

//
//  LineProgressView.swift
//  BookKeeping
//
//  Created by gy on 2022/12/2.
//

import Foundation
import UIKit

class LineProgressView : UIView {
    

    private var deActiveLayer = CAShapeLayer()
    private var activeLayer = CAShapeLayer()
    private var iconImage = UIImageView().then { attr in
        attr.image = UIImage(named: "white_tb_icon")
    }
    private var animTimer : CADisplayLink?
    var deActiveColor : UIColor? {
        didSet {
            guard deActiveColor == nil else {
                deActiveLayer.fillColor = deActiveColor?.cgColor
                return
            }
        }
    }
    
    var activeColor : UIColor? {
        didSet {
            guard activeColor == nil else {
                activeLayer.fillColor = activeColor?.cgColor
                return
            }
        }
    }
      
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initView()
    }
    
    func initView(){
        backgroundColor = .yellow
        layer.addSublayer(deActiveLayer)

        layer.addSublayer(activeLayer)
        
        addSubview(iconImage)
        iconImage.snp.makeConstraints { make in
            make.width.equalTo(20)
            make.height.equalTo(20)
        }

        animTimer = CADisplayLink.init(target: self, selector: #selector(animStep))
        guard  animTimer == nil else {
            animTimer!.add(to: .main, forMode: .default)
            return
        }
        
       
    
    }
    
    private var animProgress = 0
    private var duration = 5
    private var animPercent = 0.0
    //一秒刷新60次
    @objc
    func animStep(){
        animProgress+=1
        setNeedsLayout()
       // print("animProgress==",animProgress)
        animPercent = CGFloat(animProgress)  / (5 * 60 * 1.0)
        if(animPercent >= 1){
            animTimer?.remove(from: .main, forMode: .default)
        }
    }
    
    
    override func layoutSubviews() {
        super.layoutSubviews()
        let radius = bounds.height / 2
        
        deActiveLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
        let activeBounds = CGRect(x: CGFloat(0),y: CGFloat(0),width: bounds.width * animPercent,height: bounds.height)
        activeLayer.path = UIBezierPath(roundedRect: activeBounds,cornerRadius: radius).cgPath
        
        print("cccc",bounds.width * animPercent)
        //这种方式可以固定位置 但是设置一次之后 再次修改不会变化
//        NSLayoutConstraint.activate([
//            iconImage.leftAnchor.constraint(equalTo: self.leftAnchor,constant: CGFloat(bounds.width * animPercent)),
//            iconImage.topAnchor.constraint(equalTo: self.topAnchor),
//            iconImage.bottomAnchor.constraint(equalTo: self.bottomAnchor),
//        ])
        
        //这种设置方式可以跟着animPercent的变化动态修改iconImage 的位置
        self.iconImage.center = CGPoint(x:bounds.width * animPercent,y:bounds.height/2)
        
     
    }
}