代码之家  ›  专栏  ›  技术社区  ›  Adrian

如何获取uistackview中uiview的宽度值

  •  0
  • Adrian  · 技术社区  · 6 年前

    我有自己的看法, ProgressBar ,我用程序创建它:

    let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))
    

    我使用200的宽度创建它,然后将其添加到水平堆栈视图中。因此,视图将根据屏幕大小而增长,例如在iphone x上将增长到250。

    在这个自定义视图中,我试图使用宽度,但它始终是200,这会导致各种各样的问题。

    我真正需要的是视图在堆栈视图中的值,在我的例子中是250。

    有没有办法在我的自定义视图中获取该值?
    或者我的选择是什么?

    编辑-添加了一些代码:

    class CustomTableViewCell: UITableViewCell {
      func configure() {
         let progressBar: ProgressBar = {
             let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))
         }()
      }
    }
    

    从视图控制器调用此代码:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            if indexPath.row == 0 {
                let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! CustomTableViewCell
                cell.configure()
                return cell
    }
    

    编辑2-自定义视图代码:

    class ProgressBar: UIView {
    
        var progressView: UIView = {
            let v = UIView()
            v.backgroundColor = .white
            return v
        }()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            configure()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            configure()
        }
    
        func configure() {
            backgroundColor = UIColor(white: 1.0, alpha: 0.1)
            layer.cornerRadius = 8.0
            clipsToBounds = true
    
            progressView.frame = bounds
            progressView.frame.size.width = 0.0
            addSubview(progressView)
        }
    
        func animate(_ pct: CGFloat) -> Void {
            UIView.animate(withDuration: 1.0, animations: {
                self.progressView.frame.size.width = self.bounds.size.width * pct
            })
        }
    }
    

    edit3-调用animate

        let progressBar: ProgressBar = {
            let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))
            pb.translatesAutoresizingMaskIntoConstraints = false
    
            if data.count >= i {
                if let session = data[i - 1].session {
                    let values = Array(session).sorted(by: { $0.date.compare($1.date) == .orderedDescending })
                    var sum = 0.0
                    for value in values {
                        sum += Double(value.score)
                    }
                    pb.animate(CGFloat(sum / 40)) // returns a value between 0 and 1
                }
            }
    
            return pb;
        }()
    

    编辑4:

    enter image description here

    编辑5-添加调试约束:

    Printing description of $16:
    <UIView: 0x107d6a100; frame = (0 0; 200 16); layer = <CALayer: 0x1d003f3c0>>
    Printing description of $17:
    <StepUp.ProgressBar: 0x107d6c8e0; frame = (54.3333 0; 250 16); clipsToBounds = YES; layer = <CALayer: 0x1d0220880>>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   nayem    6 年前

    正如我在评论部分所提到的,在堆栈视图中包含progress视图不是一个明智的主意,这将需要繁琐的步骤来实现 width 更改动画。

    首先,您需要去掉显式设置 frame 即: 使用自动布局时不指定宽度和高度 . 使用 CGRectZero 相反。

    然后需要将堆栈视图(我假设您使用垂直堆栈视图)配置为:

    stackView.alignment = .leading
    

    你不能用任何 fill 在这里输入。因为如果使用fill,那么所有排列的子视图都应该具有堆栈视图的整个宽度。因此,您将无法修改它们的任何宽度以进行动画。

    现在只要提供堆栈视图 .leading 对齐普通视图(没有内部内容大小的视图)的宽度为 zero . 因此,当您运行应用程序时,您将看不到任何视图。在这里你需要做乏味的工作, 给它们每个宽度 . 一种解决方案可能是: 枚举堆栈视图的子视图,并使所有视图的宽度与堆栈视图的宽度相等,使进度视图的宽度为零

    // update these when the sub views of the view are layout already
    // otherwise stack view won't have it's own size yet 
    stackView.subviews.forEach { (view) in
        if view == progressView {
            // save this constraint for use when animating
            progressViewWidthConstraint = view.widthAnchor.constraint(equalToConstant: 0)
            progressViewWidthConstraint.isActive = true
        } else {
            view.widthAnchor.constraint(equalToConstant: stackView.frame.size.width).isActive = true
        }
    }
    

    现在你的动画应该是:

    view.layoutIfNeeded()
    progressViewWidthConstraint.constant = stackView.frame.size.width
    UIView.animate(withDuration: 2) {
        self.view.layoutIfNeeded()
    }
    

    结果如下: Animate UIView as progress view inside a UIStackView

    我做了一个 demo 如果你被困在这个过程中的任何地方。干杯