【问题标题】:Programmatically setting progressTint on ProgressView changes progress bar size以编程方式在 ProgressView 上设置 progressTint 会更改进度条大小
【发布时间】:2021-02-21 08:52:12
【问题描述】:

我花了好几天才找到这个问题的来源。

我有一个包含多行自定义表格单元格的 TableView,每个表格单元格内部都有一个进度视图。该应用会根据进度视图的填充程度要求将进度视图着色为绿色/琥珀色/红色。

我发现以编程方式设置 progressTint 会导致进度条看起来比它应该做的更满。

相关代码(tableView cellForRowAt):

    let Max:Double = MyGroup!.EndTimeSeconds - MyGroup!.StartTimeSeconds //10771
    let Progress:Double = Date().timeIntervalSince1970 - MyGroup!.StartTimeSeconds //1599.7007069587708       
    
    if (Max >= Progress) {
        Cell.DescriptionLabel.textColor = UIColor.black
        Cell.SubtitleLabel.textColor = UIColor.black
        Cell.TargetDeliveryTimeLabel.textColor = UIColor.pts_darkergrey
        Cell.ProgressView.setProgress(Float(Progress / Max), animated: false)
        Cell.ProgressView.progress = Float(Progress / Max)
        Cell.ProgressView.progressTintColor = UIColor.pts_green //if i comment these out it works.
        if (Max * 0.75 <= Progress) {
            Cell.ProgressView.progressTintColor = UIColor.pts_pbamber //if i comment these out it works.
        }
    } else {
        Cell.DescriptionLabel.textColor = UIColor.white
        Cell.SubtitleLabel.textColor = UIColor.white
        Cell.TargetDeliveryTimeLabel.textColor = UIColor.white
        Cell.ProgressView.setProgress(1, animated: false)
        Cell.ProgressView.progress = 1
        Cell.ProgressView.progressTintColor = UIColor.pts_pbred //if i comment these out it works.
    }
            
    Cell.ProgressView.layer.cornerRadius = 4
    Cell.ProgressView.clipsToBounds = true

progressTint 调用被注释掉的屏幕截图:

progressTint 调用生效的屏幕截图:

请注意,设置色调时,第二个项目的进度条错误地填充到几乎 50%。

进度条应该随着时间线性填充 - 但这将保持静止,直到进度合法地通过这一点,然后它会像往常一样继续。

我可能会看到一些东西,但问题似乎一直在影响前两项,而不是其余的(或者一样多,或者根本不)

我已经尝试过 ProgressView.progress 和 ProgressView.setProgress,以及 ProgressView.progressTintColor 和 PogressView.tintColor。

【问题讨论】:

  • ProgressViewUIProgressView 吗?还是一些自定义视图?
  • 这是一个标准的 UIProgressView。
  • 设置色调颜色不能改变进度条长度。这里有些混乱...您说“绿色/琥​​珀色/红色”,但您的第一张图片显示为蓝色?而且,根据您显示的代码,我们无法知道您获得了什么值。使用调试断点(或一些打印语句)检查MaxProgress 的值。
  • 蓝色版本的截图是我没有以编程方式设置progressTint的地方。绿色/琥珀色/红色与我在代码中设置色调的屏幕截图相同。如您所见,绿色项目进一步发展。我在两个屏幕截图之间所做的所有更改是这三个 Cell.ProgressView.progressTintColor 调用要么被注释掉,要么被注释掉。
  • 我已经澄清了问题并将值添加为 cmets。

标签: swift uitableview uiprogressview tintcolor


【解决方案1】:

经过一些搜索和测试...看来标准UIProgressView 不喜欢高度、色调颜色和/或图层修改的某些组合。

尝试用这个SimpleProgressView替换你的UIProgressView

它的默认值是:

  • backgroundColor = 白色
  • tintColor = 蓝色
  • 角半径 = 4
  • 内在高度 = 4

应该可以将其用作直接替换 - 无需对现有代码进行任何其他更改。它是 @IBDesignablecornerRadiusprogress@IBInspectable,因此您可以设置它们并在 Storyboard 中查看结果。

@IBDesignable
class SimpleProgressView: UIView {
    
    @IBInspectable public var cornerRadius: CGFloat = 0 {
        didSet {
            progressBarView.layer.cornerRadius = cornerRadius
            layer.cornerRadius = cornerRadius
        }
    }
    
    private let progressBarView = UIView()
    private var widthConstraint: NSLayoutConstraint!

    // default height of
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, height: 4.0)
    }
    
    // set the background color of the progressBarView to the tint color
    override var tintColor: UIColor! {
        didSet {
            progressBarView.backgroundColor = tintColor
        }
    }

    // update width constraint multiplier when progress changes
    @IBInspectable public var progress: Float = 0 {
        didSet {
            if let wc = widthConstraint {
                // cannot modify multiplier directly, so
                //  deactivate
                wc.isActive = false
                //  create new width constraint with percent as multiplier
                //  maximum of 1.0
                let pct = min(progress, 1.0)
                self.widthConstraint = progressBarView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(pct))
                //  activate new width constraint
                self.widthConstraint.isActive = true
            }
        }
    }
    // we can set .progress property directly, or
    // call setProgress (with optional animated parameter)
    public func setProgress(_ p: Float, animated: Bool) -> Void {
        // don't allow animation if frame height is zero
        let doAnim = animated && progressBarView.frame.height != 0
        self.progress = p
        if doAnim {
            UIView.animate(withDuration: 0.3, animations: {
                self.layoutIfNeeded()
            })
        }
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        if backgroundColor == nil {
            backgroundColor = UIColor.black.withAlphaComponent(0.1)
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    private func commonInit() -> Void {

        // default background color: black with 0.1 alpha
        if backgroundColor == nil {
            backgroundColor = UIColor.black.withAlphaComponent(0.1)
        }
        
        // default tint color
        tintColor = .blue

        // default corner radius
        cornerRadius = 4

        progressBarView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(progressBarView)
        // create width constraint
        //  progressBarView width will be set to percentage of self's width
        widthConstraint = progressBarView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.0)
        NSLayoutConstraint.activate([
            // constrain progressBarView Top / Leading / Bottom to self
            progressBarView.topAnchor.constraint(equalTo: topAnchor),
            progressBarView.leadingAnchor.constraint(equalTo: leadingAnchor),
            progressBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            // activate width constraint
            widthConstraint,
        ])
        clipsToBounds = true
    }

}

这是一个快速测试实现,比较顶部的UIProgressView 和下面的SimpleProgressView。进度条将从 10% 开始,每次点击视图都会增加 10%,并在 25%、75% 和 100% 时更改颜色:

class ViewController: UIViewController {

    let uiProgressView = UIProgressView()
    let simpleProgressView = SimpleProgressView()
    let labelA = UILabel()
    let labelB = UILabel()

    var curProgress: Float = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        labelA.text = "Default UIProgressView"
        labelB.text = "Custom SimpleProgressView"

        [labelA, uiProgressView, labelB, simpleProgressView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(v)
        }
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([

            labelA.topAnchor.constraint(equalTo: g.topAnchor, constant: 100.0),
            labelA.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            labelA.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),

            uiProgressView.topAnchor.constraint(equalTo: labelA.bottomAnchor, constant: 12.0),
            uiProgressView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            uiProgressView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            uiProgressView.heightAnchor.constraint(equalToConstant: 80.0),

            labelB.topAnchor.constraint(equalTo: uiProgressView.bottomAnchor, constant: 40.0),
            labelB.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            labelB.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
            simpleProgressView.topAnchor.constraint(equalTo: labelB.bottomAnchor, constant: 12.0),
            simpleProgressView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            simpleProgressView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            simpleProgressView.heightAnchor.constraint(equalToConstant: 80.0),
            
        ])
        
        let t = UITapGestureRecognizer(target: self, action: #selector(self.incProgress(_:)))
        view.addGestureRecognizer(t)
        
        // start at 10%
        incProgress(nil)
    }
    
    @objc func incProgress(_ g: UITapGestureRecognizer?) -> Void {
        // increment progress by 10% on each tap, up to 100%
        curProgress = min(1.0, curProgress + 0.10)

        uiProgressView.progress = curProgress
        simpleProgressView.progress = curProgress

        let formatter = NumberFormatter()
        formatter.numberStyle = .percent
        formatter.maximumFractionDigits = 2
        if let sPct = formatter.string(for: curProgress) {
            labelA.text = "Default UIProgressView: " + sPct
            labelB.text = "Custom SimpleProgressView: " + sPct
        }
        
        print(curProgress)

        if curProgress == 1.0 {
            uiProgressView.tintColor = .pts_red
            simpleProgressView.tintColor = .pts_red
        } else if curProgress >= 0.75 {
            uiProgressView.tintColor = .pts_amber
            simpleProgressView.tintColor = .pts_amber
        } else if curProgress >= 0.25 {
            uiProgressView.tintColor = .pts_green
            simpleProgressView.tintColor = .pts_green
        } else {
            uiProgressView.tintColor = .pts_blue
            simpleProgressView.tintColor = .pts_blue
        }

    }
}

我尝试匹配您的自定义颜色:

extension UIColor {
    static let pts_green = UIColor(red: 0.35, green: 0.75, blue: 0.5, alpha: 1.0)
    static let pts_amber = UIColor(red: 0.95, green: 0.7, blue: 0.0, alpha: 1.0)
    static let pts_red = UIColor(red: 0.9, green: 0.35, blue: 0.35, alpha: 1.0)
    static let pts_blue = UIColor(red: 0.25, green: 0.75, blue: 1.0, alpha: 1.0)
    static let pts_darkergrey = UIColor(white: 0.2, alpha: 1.0)
}

【讨论】:

  • 感谢您的回答。我在哪里可以找到这个 SimpleProgressView?
  • @Psiloc - 这是我回答中的第一个代码块。在 Storyboard Prototype 单元格中,将 UIProgressView 替换为普通的 UIView,然后将其自定义类分配给 SimpleProgressView 并通过 @IBOutlet 连接它。
  • 我没有一个名为 SimpleProgressView 的类,我在 Google 上也找不到任何相关信息
  • 啊,我很抱歉,这是漫长的一天!我会尽快尝试一下。
  • 这成功了!但是,我必须承认我完全不确定它的哪一部分解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多